package dao

import (
	"context"
	"fmt"
	"log"
	"mini-upload/internal/model/entity"
	"os"
	"path/filepath"
	"time"

	"github.com/glebarez/sqlite"
	"github.com/marcellowy/go-common/gogf/vconfig"
	"github.com/marcellowy/go-common/gogf/vlog"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"gorm.io/gorm/schema"
	"gorm.io/sharding"
)

var db *gorm.DB

func Connect(ctx context.Context) (err error) {
	var sqlType = vconfig.Get("db.type", "sqlite").String()

	//
	newLogger := logger.New(
		log.New(&Logger{}, "", log.LstdFlags), // io writer
		logger.Config{
			SlowThreshold:             time.Second, // Slow SQL threshold
			LogLevel:                  logger.Info, // Log level
			IgnoreRecordNotFoundError: true,        // Ignore ErrRecordNotFound error for logger
			ParameterizedQueries:      true,        // Don't include params in the SQL log
			Colorful:                  false,       // Disable color
		},
	)
	config := &gorm.Config{
		NamingStrategy: schema.NamingStrategy{
			TablePrefix:   "t_",
			SingularTable: true,
		},
		Logger: newLogger,
	}
	switch sqlType {
	case "sqlite":
		err = connectSqlite(ctx, config)
	case "mysql":
		err = connectMySQL(ctx)
	default:
		err = connectSqlite(ctx, config)
	}
	if err != nil {
		return
	}
	return autoMigrate(ctx)
}

func connectSqlite(ctx context.Context, option ...gorm.Option) (err error) {
	var file = vconfig.Get("db.path", "data.db").String()
	dir := filepath.Dir(file)
	if _, err = os.Stat(dir); err != nil {
		if !os.IsNotExist(err) {
			vlog.Warning(ctx, err)
			return
		}
		if err = os.MkdirAll(dir, os.ModePerm); err != nil {
			vlog.Warning(ctx, err)
			return
		}
	}
	if db, err = gorm.Open(sqlite.Open(file), option...); err != nil {
		vlog.Error(ctx, err, file)
		return
	}
	return
}

func connectMySQL(ctx context.Context) (err error) {
	return fmt.Errorf("not support mysql")
}

func autoMigrate(ctx context.Context) (err error) {
	var tables []any
	tables = append(tables, &entity.Attachment{})
	err = db.Use(sharding.Register(sharding.Config{
		ShardingKey:    "attachment_id",
		NumberOfShards: 10,
	}, "t_attachment"))
	if err != nil {
		vlog.Warning(ctx, err)
		return
	}
	tables = append(tables)
	return db.AutoMigrate(tables...)
}
